﻿using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using HslCommunication.Profinet.Siemens;
using HslCommunication.Core.Pipe;
using HslCommunication;
using HslCommunication.Core.Device;

namespace DataCollectService
{
    [HubName("DataCollectHub")]
    public class DataCollectHub: Hub
    {
        static List<DeviceConfig> listDeviceConfig = new List<DeviceConfig>();
        static List<Thread> listTasks = new List<Thread>();
        static List<Protocol> listDBConfig = new List<Protocol>();
        static DataInterfaceHelper dataInterfaceHelper;

        /// <summary>
        /// 初始化所有设备采集配置
        /// </summary>
        public void InitDeviceCollectConfig(string _deviceConfigStr,string _protocalStr)
        {
            listDeviceConfig = _deviceConfigStr.FromJSON<List<DeviceConfig>>();
            Dictionary<string, string> deviceProtocol = new Dictionary<string, string>();
            //循环设备列表
            foreach (var deviceObj in listDeviceConfig)
            {
                deviceProtocol.Add(deviceObj.DeviceNo,deviceObj.DataBaseConfig);
            }
            //设置协议配置对象
            dataInterfaceHelper = new DataInterfaceHelper(deviceProtocol);
            dataInterfaceHelper.listProtocal = _protocalStr.FromJSON<List<Protocol>>();
            //开启循环返回设备状态
            GetAllDeviceStatus();
        }
        /// <summary>
        /// 开启全部采集设备配置
        /// </summary>
        public void PlayAllDeviceCollect()
        {
            //终止当前所有运行线程
            foreach (var task in listTasks)
            {
                task.Abort();
            }
            listTasks.Clear();
            foreach (var deviceObj in listDeviceConfig)
            {
                Thread threadDevice = new Thread(() =>
                {
                    PlayDeviceCollect(deviceObj);
                });
                threadDevice.Name = deviceObj.DeviceNo;
                threadDevice.Start();
                listTasks.Add(threadDevice);
            }
        }
        /// <summary>
        /// 开启单个采集设备配置
        /// </summary>
        /// <param name="deviceNo"></param>
        public void PlaySingleDeviceCollect(string deviceNo)
        {
            //终止当前所有运行线程
            foreach (var task in listTasks)
            {
                if(task.Name == deviceNo)
                {
                    task.Abort();
                    listTasks.Remove(task);
                    break;
                }
            }
            foreach (var deviceObj in listDeviceConfig)
            {
                if(deviceObj.DeviceNo == deviceNo)
                {
                    Thread threadDevice = new Thread(() =>
                    {
                        PlayDeviceCollect(deviceObj);
                    });
                    threadDevice.Name = deviceObj.DeviceNo;
                    threadDevice.Start();
                    listTasks.Add(threadDevice);
                }
            }
        }

        /// <summary>
        /// 停止全部采集设备配置
        /// </summary>
        public void StopAllDeviceCollect()
        {
            //终止当前所有运行线程
            foreach (var task in listTasks)
            {
                task.Abort();
            }
            listTasks.Clear();

            foreach (var deviceConfig in listDeviceConfig)
            {
                deviceConfig.IsRunning = false;
            }

        }
        /// <summary>
        /// 暂停单个采集设备配置
        /// </summary>
        /// <param name="deviceNo"></param>
        public void StopSingleDeviceCollect(string deviceNo)
        {
            //终止当前所有运行线程
            foreach (var task in listTasks)
            {
                if (task.Name == deviceNo)
                {
                    task.Abort();
                    listTasks.Remove(task);
                    break;
                }
            }
            var deviceConfig = listDeviceConfig.Where(x => x.DeviceNo == deviceNo).FirstOrDefault();
            if(deviceConfig!=null)
            {
                deviceConfig.IsRunning = false;
            }
        }


        public void PlayDeviceCollect(DeviceConfig deviceConfig)
        {
            try
            {
                //配置信息如果不为空
                if(!string.IsNullOrEmpty(deviceConfig.ProtocalConfig))
                {
                    ProtocalInfo protocalInfo = deviceConfig.ProtocalConfig.FromJSON<ProtocalInfo>();
                    //此部分逐一枚举，按实际项目来增加协议要求
                    #region 西门子-S7-S1200
                    if (protocalInfo.TypeName == "Siemens Plc [西门子]" && protocalInfo.TypeDetailName == "S7-S1200")
                    {
                        SiemensS7Net siemensTcpNet = new SiemensS7Net(SiemensPLCS.S1200);
                        var connectConfigObj = protocalInfo.ConnectConfig.FromJSON<dynamic>();
                        PipeTcpNet pipe = new PipeTcpNet(connectConfigObj.IP.toString(), connectConfigObj.Port.toString());
                        pipe.ConnectTimeOut = 5000;
                        pipe.ReceiveTimeOut = 10000;
                        siemensTcpNet.CommunicationPipe = pipe;

                        siemensTcpNet.Rack = 0;
                        siemensTcpNet.Slot = 0;
                        OperateResult connect = DeviceConnectPLC(siemensTcpNet);
                        if(connect.IsSuccess)
                        {
                            string note = "设备编码:" + deviceConfig.DeviceNo + ",协议配置:" + deviceConfig.ProtocalConfig +",连接成功";
                            Log.SaveNote(note);
                            //通知上位机设备状态
                            deviceConfig.IsRunning = true;
                            
                            //开启采集参数线程
                            foreach (var item in deviceConfig.VarList)
                            {
                                System.Timers.Timer varTimer = new System.Timers.Timer(1000* item.VarRequency);
                                varTimer.Elapsed += new System.Timers.ElapsedEventHandler((sender,e) => {
                                    try
                                    {
                                        string collectResult = "";
                                        switch (item.VarType)
                                        {
                                            case "byte":
                                                {
                                                    var result = siemensTcpNet.ReadByte(item.VarPath); 
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                                 
                                            case "short":
                                                {
                                                    var result = siemensTcpNet.ReadInt16(item.VarPath);
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                            case "ushort":
                                                {
                                                    var result = siemensTcpNet.ReadUInt16(item.VarPath);
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                            case "int":
                                                {
                                                    var result = siemensTcpNet.ReadInt32(item.VarPath);
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                            case "uint":
                                                {
                                                    var result = siemensTcpNet.ReadUInt32(item.VarPath);
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                            case "float":
                                                {
                                                    var result = siemensTcpNet.ReadFloat(item.VarPath);
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                            case "double":
                                                {
                                                    var result = siemensTcpNet.ReadDouble(item.VarPath);
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                            case "string":
                                                {
                                                    var result = siemensTcpNet.ReadString(item.VarPath);
                                                    if (result.IsSuccess)
                                                    {
                                                        collectResult = result.Content.ToString();
                                                    }
                                                    else
                                                    {
                                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + result.Message;
                                                        Log.SaveNote(varNote);
                                                    }
                                                    break;
                                                }
                                        }
                                        if(!string.IsNullOrEmpty(collectResult))
                                        {
                                            //存储采集信息
                                            dataInterfaceHelper.insertKV(deviceConfig.DeviceNo, DateTime.Now, item.VarName, collectResult,deviceConfig.SaveDataTime==""?0:int.Parse(deviceConfig.SaveDataTime));
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        string varNote = "设备编码:" + deviceConfig.DeviceNo + ",参数地址:" + item.VarPath + ",取值失败:" + ex.Message;
                                        Log.SaveNote(varNote);
                                    }
                                });
                                varTimer.AutoReset = true;
                                varTimer.Enabled = true;
                            }
                        }
                        else
                        {
                            string note = "设备编码:" + deviceConfig.DeviceNo + ",协议配置:" + deviceConfig.ProtocalConfig + "连接失败:" + connect.Message;
                            Log.SaveNote(note);
                            deviceConfig.IsRunning = false;
                        }
                    }
                    #endregion

                }
            }
            catch
            {
            }
        }

        protected OperateResult DeviceConnectPLC(DeviceTcpNet device)
        {
            if (device.CommunicationPipe.GetType() == typeof(PipeDtuNet))
            {
                return OperateResult.CreateSuccessResult();
            }
            else
                return device.ConnectServer();
        }

        /// <summary>
        /// 获取所有设备采集状态
        /// </summary>
        public void GetAllDeviceStatus()
        {
            Thread threadGetAllDeviceStatus = new Thread(() =>
            {
                while (true)
                {
                    Clients.All.OnGetAllDeviceStatus(listDeviceConfig.ToJSON());
                    Thread.Sleep(1000);
                }
            });
            threadGetAllDeviceStatus.Start();
        }


    }
}
